using System;
using System.Runtime.InteropServices;

namespace Shraga.Client
{

	struct SecPkgContext_Names
	{
		public string sUsername;
	}

	struct SecHandle 
	{
		public ulong dwLower;
		public ulong dwUpper;
	}
	/// <summary>
	/// Summary description for Authenticator.
	/// </summary>
	public class Authenticator
	{

		/*
		 *	Now pay attention here, youngster.
		 */

		[DllImport("secur32.dll")]
		private static extern long AcquireCredentialsHandle(
			string name,				// [in] name of principal. "" = principal of current security context
			string package,				// [in] name of package
			int flags,					// [in] flags indicating use.
			int logon,					// [in] pointer to logon identifier.  NULL = we're not specifying the id of another logon session
			int data,					// [in] package-specific data.  NULL = default credentials for security package
			int key,					// [in] pointer to GetKey function.  NULL = we're not using a callback to retrieve the credentials
			int val,					// [in] value to pass to GetKey
			ref SecHandle phCredential,	// [out] credential handle
			ref IntPtr tsExpiry			// [out] lifetime of the returned credentials
			);

		[DllImport("secur32.dll")]
		private static extern long QueryCredentialsAttributes(
			ref SecHandle phCredential, //SUPRIZE! You need a REF here, for some oddball reason.
			int SECPKG_CRED_ATTR_NAMES,
			ref SecPkgContext_Names secPkgCredentials_Names);

		public Authenticator()
		{
			//FOOL
		}

		public string Authenticate(string expected)
		{
			string backup = expected;
			//	For some reason, the AcquireCredentialsHandle method
			//stomps on this string. So make a silly backup for a quick-fix.
			//	Don't ask stupid questions.
			backup = backup + "";

			IntPtr ts = IntPtr.Zero;
			SecHandle cred = new SecHandle();
			SecPkgContext_Names names = new SecPkgContext_Names();
			String name;

			try
			{
				AcquireCredentialsHandle("", "Kerberos", 2,0,0,0,0, ref cred, ref ts);
				QueryCredentialsAttributes(ref cred, 1, ref names);
			}
			catch (Exception e)
			{
				throw (new System.Security.SecurityException("Computer is not in domain.", e));
			}

			name = (names.sUsername).ToLower();
            int i = name.IndexOf('@', 0);
			string tmp = (name.Remove(0, i + 1));

			//System.Windows.Forms.MessageBox.Show("Compare:\n" + tmp + "\nAnd\n" + "d8200.mil" + "\nResult:\n" + tmp.CompareTo(expected).ToString());
			if ((tmp.CompareTo(expected) != 0))
			{
				throw (new System.Security.SecurityException("Computer is not in domain."));
			}
			return name.Substring(0, i);
		}
	}
}